<!--
 * @Date: 2023-04-19 22:10:39
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2023-04-28 18:11:17
 * @Description: 多选级联组件
-->
<template>
  <el-cascader
    v-model="curValue"
    ref="cascaderRef"
    :props="optionsProps"
    @visible-change="visibleChangeHandle"
    @change="handleChange"
  />
</template>

<script setup lang="ts">
import { computed, onBeforeMount, ref, type Ref } from 'vue'
import { apiFindDictList, apiFindDictItem } from '@/api/common'
import { ElCascader } from 'element-plus'
import type { CascaderProps } from 'element-plus'
const props = defineProps({
  modelValue: String,
  dictType: {
    // 字典类型
    type: String,
    default: ''
  },
  parentValue: String, // 父级值
  parentId: {
    type: String,
    default: '-1'
  }, // 父级id
  showableRootVals: {
    // 配置第一项可选项，若不配置则所有项目可选
    type: Array,
    default: () => []
  },
  showableSubVals: {
    // 配置第二项可选项，若不配置则所有项目可选
    type: Array,
    default: () => []
  },
  showableSetReverse: Boolean, // 是否反向配置
  splitChar: {
    // 级联文本拼接符号
    type: String,
    default: '/'
  },
  multiple: Boolean // 是否多选
})

const emits = defineEmits(['update:modelValue', 'get-full-label', 'get-last-label', 'get-full-value', 'on-change'])

// 当前级联选项值
const curValue: Ref<any> = ref([])

// 回填初始化
const initValue = async () => {
  if (props.modelValue) {
    curValue.value = []
    if (props.multiple) {
      const valueArr = props.modelValue ? props.modelValue.split(',') : []
      for (let i = 0; i < valueArr.length; i++) {
        const resArr: any = await initValueDiff(valueArr[i])
        curValue.value.push(resArr)
      }
      console.log(curValue.value, '---')
    } else {
      let curLastLevVal = props.modelValue || '' // 当前最后一层的值
      const resArr: any = await initValueDiff(curLastLevVal)
      curValue.value = resArr
    }
  }
}
onBeforeMount(() => {
  initValue()
})

// 向上回溯处理
const initValueDiff = (lastValue: string) => {
  return new Promise(async (resolve, reject) => {
    let curLastLevVal = lastValue // 最后一级的值
    let findTimes = 0 //向上追溯次数
    const itemArr: string[] = []

    // 向上追溯最多5级
    while (findTimes <= 5) {
      const res = await apiFindDictItem({
        type: props.dictType as string,
        value: curLastLevVal as string
      })
      const { isSuccess, errorMsg, data } = res
      if (isSuccess) {
        if (data) {
          curLastLevVal = data.parentValue
          itemArr.push(data.value)
          findTimes++

          // 当前层级父id以及父级值等于传入的父级id、值时，停止追溯，表示已经到最上级了
          if (data.parentValue === props.parentValue || data.parentId === props.parentId) {
            findTimes = 100
          }
        } else {
          findTimes = 100
          reject([])
        }
      } else {
        findTimes = 100
        window.$Message.error(errorMsg)
        reject([])
      }
    }

    resolve(itemArr.reverse())
  })
}

// 动态加载配置
const optionsProps: CascaderProps = {
  lazy: true,
  checkStrictly: true,
  multiple: props.multiple,
  lazyLoad(node, resolve) {
    const { level, value } = node
    apiFindDictList({
      type: props.dictType,
      parentId: props.parentId,
      parentValue: value?.toString() || props.parentValue
    }).then((res) => {
      const { isSuccess, data, errorMsg } = res
      if (isSuccess) {
        let nodes: any = []
        if (data) {
          let resData = data
          // 一级过滤
          if (level === 0 && props.showableRootVals.length) {
            resData = resData.filter((item: any) => {
              const condition = props.showableRootVals.includes(item.value)
              return props.showableSetReverse ? !condition : condition
            })
          }

          // 二级过滤
          if (level === 1 && props.showableSubVals.length) {
            resData = resData.filter((item: any) => props.showableSubVals.includes(item.value))
          }

          nodes = resData.map((item: any) => {
            return {
              ...item,
              leaf: !(item.childrenSum > 0)
            }
          })
        } else {
          nodes = []
        }
        setTimeout(() => {
          resolve(nodes)
        }, 200)
      } else {
        window.$Message.error(errorMsg)
      }
    })
  }
}

// 选择回调
const cascaderRef = ref(null) // 组件实例
const curCheckNode = ref({})
const handleChange = (value: any) => {
  const refObj: any = cascaderRef.value
  const nodes: Array<any> = refObj.getCheckedNodes() // 获取选中的节点
  if (props.multiple) {
    const newArr: any = []
    for (let node of nodes) {
      const parentNode = node.parent
      if (parentNode) {
        if (node.children.length > 0) {
          // 有子项，不是最后一级
          const parentCheck = diff(node.parent)
          if (parentCheck) {
          } else {
            newArr.push([node.pathValues])
          }
        } else {
          // 最后一级
          const parentCheck = diff(node.parent)
          if (parentCheck) {
            // 父组件为选中 无须处理
          } else {
            newArr.push([node.pathValues])
          }
        }
      } else {
        // 一级选项直接插入
        newArr.push([node.value])
      }
    }
    // curValue.value = newArr
    console.log(newArr, 11)
  } else {
    const { pathLabels, pathValues } = nodes[0]
    const lastValue = pathValues.length ? pathValues[pathValues.length - 1] : ''
    const fullValue = pathLabels.join()
    const lastLabel = pathLabels.length ? pathLabels[pathLabels.length - 1] : ''
    const fullLabel = pathLabels.join(props.splitChar)
    emits('get-full-value', fullValue) // 完整层级值
    emits('get-full-label', fullLabel) // 完整层级文本
    emits('get-last-label', lastLabel) // 最后一级文本
    emits('update:modelValue', lastValue) // 最后一级值
    emits('on-change', nodes[0])
  }
}

const diff = (pNode: any) => {
  if (pNode.checked) return pNode.checked

  if (pNode.parent) {
    diff(pNode.parent)
  } else {
    return false
  }
}
const visibleChangeHandle = (visible: any) => {
  if (!visible) {
    console.log(curCheckNode.value, 111)
  }
}
</script>

<style scoped></style>
